package org.walklink.common.util;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Objects;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 基于Jackson的Json工具类，提供对象与字符串之间的相互转换。
 *
 * @author lidishan
 */
public class JsonUtil {
    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    private static final Logger LOGGER = LoggerFactory.getLogger(JsonUtil.class);

    static {
        // 对象的所有字段全部列入
        OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        // 取消默认转换timestamps形式
        OBJECT_MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        // 忽略空Bean转json的错误
        OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        // 所有的日期格式都统一为以下的样式，即yyyy-MM-dd HH:mm:ss
        OBJECT_MAPPER.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        // 忽略 在json字符串中存在，但是在java对象中不存在对应属性的情况。防止错误
        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * 对象转Json格式字符串
     *
     * @param object 对象
     * @return Json格式字符串
     */
    public static <T> String object2String(T object) throws JsonProcessingException {
        if (Objects.isNull(object)) {
            return null;
        }

        return object instanceof String ? (String) object : OBJECT_MAPPER.writeValueAsString(object);
    }

    /**
     * 对象转Json格式字符串
     *
     * @param object 对象
     * @return 美化的Json格式字符串
     */
    public static <T> String object2StringPretty(T object) throws JsonProcessingException {
        if (Objects.isNull(object)) {
            return null;
        }

        return object instanceof String ? (String) object
                : OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(object);
    }

    /**
     * 字符串转换为自定义对象
     *
     * @param str   要转换的字符串
     * @param clazz 自定义对象的class对象
     * @return 自定义对象
     */
    public static <T> T string2Object(String str, Class<T> clazz) throws IOException {
        if (Objects.isNull(str) || str.isEmpty() || Objects.isNull(clazz)) {
            return null;
        }

        return clazz.equals(String.class) ? (T) str : OBJECT_MAPPER.readValue(str, clazz);
    }

    /**
     * 字符串转换为自定义对象
     *
     * @param str           要转换的字符串
     * @param typeReference 自定义对象的class对象
     * @return T
     */
    public static <T> T string2Object(String str, TypeReference<T> typeReference) throws IOException {
        if (Objects.isNull(str) || str.isEmpty() || Objects.isNull(typeReference)) {
            return null;
        }

        return (T) (typeReference.getType().equals(String.class) ? str : OBJECT_MAPPER.readValue(str, typeReference));
    }

    /**
     * 字符串转换为JsonNode
     *
     * @param str 要转换的字符串
     * @return 自定义对象
     */
    public static JsonNode string2JsonNode(String str) throws IOException {
        if (Objects.isNull(str) || str.isEmpty()) {
            return null;
        }

        return OBJECT_MAPPER.readTree(str);
    }

    /**
     * 对象转Json格式字符串（吃掉异常，返回null）
     *
     * @param object 对象
     * @return Json格式字符串
     * @see #object2String(Object)
     */
    public static <T> String silentObject2String(T object) {
        try {
            return object2String(object);
        } catch (JsonProcessingException e) {
            LOGGER.error("[ERROR_silentObject2String]object={}", object, e);
            return null;
        }
    }

    /**
     * 对象转Json格式字符串（吃掉异常，返回null）
     *
     * @param object 对象
     * @return 美化的Json格式字符串
     * @see #object2StringPretty(Object)
     */
    public static <T> String silentObject2StringPretty(T object) {

        try {
            return object2StringPretty(object);
        } catch (JsonProcessingException e) {
            LOGGER.error("[ERROR_silentObject2StringPretty]object={}", object, e);
            return null;
        }
    }

    /**
     * 字符串转换为自定义对象（吃掉异常，返回null）
     *
     * @param str   要转换的字符串
     * @param clazz 自定义对象的class对象
     * @return 自定义对象
     * @see #string2Object(String, Class)
     */
    public static <T> T silentString2Object(String str, Class<T> clazz) {
        try {
            return string2Object(str, clazz);
        } catch (Exception e) {
            LOGGER.error("[ERROR_silentString2Object]str={},clazz={}", str, clazz, e);
            return null;
        }
    }

    /**
     * 字符串转换为自定义对象（吃掉异常，返回null）
     *
     * @param str           要转换的字符串
     * @param typeReference 自定义对象的class对象
     * @return T
     * @see #string2Object(String, TypeReference)
     */
    public static <T> T silentString2Object(String str, TypeReference<T> typeReference) {
        try {
            return string2Object(str, typeReference);
        } catch (IOException e) {
            LOGGER.error("[ERROR_silentString2Object]str={},typeReference={}", str, typeReference, e);
            return null;
        }
    }

    /**
     * 字符串转换为JsonNode（吃掉异常，返回null）
     *
     * @param str 要转换的字符串
     * @return JsonNode
     * @see #string2JsonNode(String)
     */
    public static JsonNode silentString2JsonNode(String str) {
        try {
            return string2JsonNode(str);
        } catch (IOException e) {
            LOGGER.error("[ERROR_silentString2JsonNode]str={}", str, e);
            return null;
        }
    }
}